﻿#region 命名空间

using System;
using System.Collections;
using System.Collections.Specialized;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using WinnerCMS.Common;

#endregion

namespace WinnerCMS.BLL.PageFactory
{
    /// <summary>
    /// 模仿Repeater的简单控件
    /// </summary>
    [ParseChildren(true), PersistChildren(false)]
    public class DataBox : Control, INamingContainer
    {
        #region 特性、功能定义

        /// <summary>
        /// 空数据是否显示
        /// </summary>
        [PersistenceMode(PersistenceMode.Attribute), Description("空数据是否显示"), DefaultValue(true)] private bool
            _emptyDataVisible = true;

        public bool EmptyDataVisible
        {
            get { return this._emptyDataVisible; }
            set { this._emptyDataVisible = value; }
        }

        #endregion

        #region 模板的定义

        /// <summary>
        /// 第一条数据的模板
        /// </summary>
        [TemplateContainer(typeof (ItemContainer)), PersistenceMode(PersistenceMode.InnerProperty),
         Description("第一条数据的模板")]
        public ITemplate FirstItemTemplate { get; set; }

        /// <summary>
        /// 第二条数据的模板
        /// </summary>
        [TemplateContainer(typeof (ItemContainer)), PersistenceMode(PersistenceMode.InnerProperty),
         Description("第二条数据的模板")]
        public ITemplate SecondItemTemplate { get; set; }

        /// <summary>
        /// 间隔模板
        /// </summary>
        [TemplateContainer(typeof (ItemContainer)), PersistenceMode(PersistenceMode.InnerProperty), Description("间隔模板")]
        public ITemplate AlternatingItemTemplate { get; set; }

        /// <summary>
        /// 定义如何显示各项之间的分隔符模板
        /// </summary>
        [TemplateContainer(typeof (RepeaterItem)), Browsable(false), PersistenceMode(PersistenceMode.InnerProperty)]
        public virtual ITemplate SeparatorTemplate { get; set; }

        /// <summary>
        /// 元素模板
        /// </summary>
        [TemplateContainer(typeof (ItemContainer)), Browsable(false), DefaultValue(null),
         PersistenceMode(PersistenceMode.InnerProperty), Description("元素模板")]
        public ITemplate ItemTemplate { get; set; }


        /// <summary>
        /// 头模板
        /// </summary>
        [TemplateContainer(typeof (ItemContainer)), Browsable(false), DefaultValue(null),
         PersistenceMode(PersistenceMode.InnerProperty), Description("头模板")]
        public ITemplate HeaderTemplate { get; set; }

        /// <summary>
        /// 脚模板
        /// </summary>
        [TemplateContainer(typeof (ItemContainer)), Browsable(false), DefaultValue(null),
         PersistenceMode(PersistenceMode.InnerProperty), Description("脚注模板")]
        public ITemplate FooterTemplate { get; set; }

        #region 数据不存在模板

        [PersistenceMode(PersistenceMode.InnerProperty), Description("空数据模板"), TemplateContainer(typeof (ItemContainer)),
         DefaultValue("数据不存在"), Browsable(false)]
        public virtual ITemplate EmptyDataTemplate { get; set; }

        #endregion

        #endregion

        #region 数据源

        //数据源

        [DefaultValue(null), Bindable(true), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public virtual object DataSource { get; set; }

        #endregion

        #region 重写

        /// <summary>
        /// 当用户端调用DataBind，则表示准备好了数据源，此时可以开始创建子模板
        /// </summary>
        /// <param name="e"></param>
        protected override void OnDataBinding(EventArgs e)
        {
            base.OnDataBinding(e);
            Controls.Clear();
            ClearChildViewState();
            CreateControlHierarchy(true);
        }

        #endregion

        #region 辅助方法

        /// <summary>
        /// 根据是否使用DataSource创建元素模板
        /// </summary>
        /// <param name="useDataSource">是否使用DataSource</param>
        private void CreateControlHierarchy(bool useDataSource)
        {
            //添加头模板
            if (HeaderTemplate != null)
            {
                using (ItemContainer rc = new ItemContainer(-1, null))
                {
                    HeaderTemplate.InstantiateIn(rc);
                    Controls.AddAt(0, rc);
                }
            }

            //作为创建元素模板的数据源
            IEnumerator data;

            //根据用户是否使用自己的数据源来给data赋值
            if (useDataSource)
            {
                data = getIEnumerator(DataSource);
            }
            else
            {
                int count = (int) ViewState["itemCount"] - 1;
                IEnumerable nullArray = new object[count];
                data = nullArray.GetEnumerator();
            }

            //创建元素模板

            //计算创建了多少子模板
            int itemIndex = 0;

            while (data.MoveNext() && ItemTemplate != null)
            {
                ItemContainer DataItem = new ItemContainer(itemIndex, data.Current);
                if (itemIndex == 0 && FirstItemTemplate != null)
                {
                    FirstItemTemplate.InstantiateIn(DataItem);
                    Controls.Add(DataItem);
                }
                else if (itemIndex == 1 && SecondItemTemplate != null)
                {
                    SecondItemTemplate.InstantiateIn(DataItem);
                    Controls.Add(DataItem);
                }
                else if (MyMath.IsOdd(itemIndex + 1) == false && AlternatingItemTemplate != null)
                {
                    AlternatingItemTemplate.InstantiateIn(DataItem);
                    Controls.Add(DataItem);
                }
                else
                {
                    ItemTemplate.InstantiateIn(DataItem);
                    Controls.Add(DataItem);
                }

                if (SeparatorTemplate != null)
                {
                    using (ItemContainer s = new ItemContainer(-1, null))
                    {
                        SeparatorTemplate.InstantiateIn(s);
                        Controls.Add(s);
                    }
                }
                itemIndex++;
                DataItem.Dispose();
            }

            if (itemIndex == 0 && EmptyDataTemplate != null)
            {
                using (ItemContainer rc = new ItemContainer(-1, null))
                {
                    EmptyDataTemplate.InstantiateIn(rc);
                    Controls.Add(rc);
                }
            }
            //添加脚注模板
            if (FooterTemplate != null)
            {
                using (ItemContainer rc = new ItemContainer(-1, null))
                {
                    FooterTemplate.InstantiateIn(rc);
                    Controls.AddAt(Controls.Count, rc);
                }
            }
            //确认子模板创建完毕
            ChildControlsCreated = true;

            if (itemIndex == 0)
            {
                Visible = EmptyDataVisible;
            }
        }

        /// <summary>
        /// 得到数据源的IEnumerator形式
        /// </summary>
        /// <param name="source">数据源</param>
        /// <returns>IEnumerator接口化的数据源</returns>
        private IEnumerator getIEnumerator(object source)
        {
            IEnumerable data;

            if (source is IEnumerable)
                data = (IEnumerable) source;
            else if (source is IList)
                data = (IEnumerable) source;
            else if (source is DataSet)
                data = ((DataSet) source).Tables[0].DefaultView;
            else if (source is DataTable)
                data = ((DataTable) source).DefaultView;
            else
                data = null;

            return data.GetEnumerator();
        }

        #endregion

        #region 事件处理

        //委托中使用CommandEventArgs，这样才可以获得按钮事件的丰富信息
        public delegate void EventHandler(object sender, CommandEventArgs e);

        [Description("处理模板中按钮的单击事件"), Category("事件")]
        public event EventHandler RedItemCommand;

        /// <summary>
        /// 截获模板中的CommandEventArgs，发布自己的事件RedItemCommand
        /// </summary>
        /// <param name="source">事件源，按照我们在RedContainer的定义，这里应该是容器控件</param>
        /// <param name="args">包含事件数据的 EventArgs 对象。</param>
        /// <returns>true 在这里取消事件</returns>
        protected override bool OnBubbleEvent(object source, EventArgs args)
        {
            if (args is CommandEventArgs)
                if (RedItemCommand != null)
                {
                    CommandEventArgs e = (CommandEventArgs) args;
                    RedItemCommand(this, e);
                }
            return true;
        }

        #endregion

        #region 容器控件类

        /// <summary>
        /// 容器控件
        /// </summary>
        public class ItemContainer : Control, INamingContainer
        {
            public object DataItem { get; private set; }

            public int ItemIndex { get; private set; }

            public ItemContainer(int itemIndex, object dataItem)
            {
                ItemIndex = itemIndex;
                DataItem = dataItem;
            }
        }

        #endregion
    }
}